{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 问题：Django 中 csrf 的实现机制\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "面试官想从这道题中考察面试人什么？\n",
    "答案\n",
    "django 第一次响应来自某个客户端的请求时，后端随机产生一个 token 值，把这个 token 保存在 SESSION 状态中；同时后端把这个 token 放到 cookie 中交给前端页面；\n",
    "在所有的 POST 表单时，必须包含一个csrfmiddlewaretoken字段（只需要在模板里加一个 csrf_token标签，django 就会自动帮你生成）；\n",
    "下次前端需要发起 POST 请求的时候把这个 token 值加入到请求数据或者头信息中，一起传给后端；Cookies:{csrftoken:xxxxx}；\n",
    "后端校验前端请求 cookie 中带过来的csrftoken和提交的表单里的csrfmiddlewaretoken 字段的值是否一样，如果一样，则表明这是一个合法的请求，否则，这个请求可能是来自于别人的 csrf 攻击，返回 403 Forbidden；\n",
    "在所有 ajax POST 请求里，添加一个 X-CSRFTOKEN header，其值为 cookie 里的 csrftoken 的值。\n",
    "拓展\n",
    "django 的 CSRF 中间件和模板标签提供了易于使用的跨站点请求伪造请求（CSRF）保护。当恶意网站包含链接，表单按钮或某些 JavaScript 时，会使用访问浏览器中恶意网站的登录用户的凭据来对您的网站执行某些操作，就会发生这种类型的攻击。django 的 CSRF 保护还涵盖了一种相关的攻击类型“登录 CSRF”，即攻击站点在其中诱骗用户的浏览器使用用户的凭据登录到该站点。\n",
    "\n",
    "CSRF 是什么\n",
    "用户 C 打开浏览器，访问受信任网站 A，输入用户名和密码请求登录网站 A；\n",
    "\n",
    "在用户信息通过验证后，网站 A 产生 Cookie 信息并返回给浏览器，此时用户登录网站 A 成功，可以正常发送请求到网站 A；\n",
    "\n",
    "用户未退出网站 A 之前，在同一浏览器中，打开一个 TAB 页访问网站 B；\n",
    "\n",
    "网站 B 接收到用户请求后，返回一些攻击性代码，并发出一个请求要求访问第三方站点 A；\n",
    "\n",
    "浏览器在接收到这些攻击性代码后，根据网站 B 的请求，在用户不知情的情况下携带 Cookie 信息，向网站 A 发出请求。网站 A 并不知道该请求其实是由 B 发起的，所以会根据用户 C 的 Cookie 信息以 C 的权限处理该请求，导致来自网站 B 的恶意代码被执行。\n",
    "\n",
    "Django 中使用 CSRF 防护\n",
    "Django 防止此类的攻击机制就是按答案中的三步，在客户端页面上添加 csrftoken，服务器端进行验证，服务器端验证的工作通过 'django.middleware.csrf.CsrfViewMiddleware' 这个中间层来完成。我们知道 Django 是通过配置文件 settings.py 去配置中间件的，但是要记住，这个 CsrfViewMiddleware 中间件的位置必须在其它视图中间件的前面。\n",
    "\n",
    "具体怎么操作的，无非就是两点：\n",
    "\n",
    "在表单当中附加csrftoken；\n",
    "通过 request 请求中添加X-CSRFToken请求头。而其它的就交给 Django 就可以了。\n",
    "小结\n",
    "这个章节里面的问题都是和 Django 相关的热门问题。从最开始的 Django 框架，再到 Django 的 route 映射机制，重定向，缓存，安全，发布等等。虽然短短的篇幅不能让你立马变成 Django 专家，但一定程度上也能够解答不少同学关于 Django 的一些疑惑。\n",
    "\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
